﻿(function ($) {
    /*
    Validation Singleton
    */
    var Validation = function () {

        var rules = {

            phone: {
                check: function (value) {
                    if (value) {
                        return testPattern(value, "^[0-9x -\\.\\(\\)]{10,}$");
                    }
                    return true;
                },
                msg: "Nhập"
            },
            email: {
                check: function (value) {
                    if (value)
                        return testPattern(value, "^([\\w-]+(?:\\.[\\w-]+)*)@((?:[\\w-]+\\.)*\\w[\\w-]{0,66})\\.([a-z]{2,6}(?:\\.[a-z]{2})?)$");
                    return true;
                },
                msg: "Nhập"
            },
            number: {
                check: function (value) {
                    if (value)
                        return testPattern(value, "^[0-9, ]*\\.?[0-9 ]*$");
                    return true;
                },
                msg: "Nhập"
            },
            money: {
                check: function (value) {
                    if (value)
                        return testPattern(value, "^ *\\$?[0-9, ]*\\.?[0-9 ]*$");
                    return true;
                },
                msg: "Nhập"
            },
            zipcode: {
                check: function (value) {
                    if (value)
                        return testPattern(value, "(^\\d{5}$)|(^\\d{5}\-?\\d{4}$)");
                    return true;
                },
                msg: "Nhập"
            },
            ssn: {
                check: function (value) {
                    if (value)
                        return testPattern(value, "^[0-9]{3}\-?[0-9]{2}\-?[0-9]{4}$");
                    return true;
                },
                msg: "Nhập"
            },
            text: {
                check: function (value) {
                    if (value) {
                        for (var i = 0; i < value.length; i++) {
                            if (value[i] == '>' || value[i] == '<') {
                                return false;
                            }
                        }
                    }
                    return true;
                },
                msg: "Nhập"
            },
            date: {
                check: function (value) {
                    if (value) {
                        var returned = testPattern(value, "^(0?[1-9]|[12][0-9]|3[01])/(0?[1-9]|1[012])/(19\\d\\d|(20)?[0-7][0-8])$");
                        return returned;
                    }

                    return true;
                },
                msg: "Nhập"
            },
            datetime: {
                check: function (value) {
                    if (value) {
                        var re = /[0-1]\d\/[0-2]\d|[3][01]\/\d{4}|\d{2} [0-1]\d:[0-5]\d [AP][M]/;

                        if (re.test(value)) {
                            return true;
                        }
                        else
                            return false;
                    }

                    return true;
                },
                msg: "Nhập"
            },
            time: {
                check: function (value) {
                    if (value)
                        return testPattern(value, "^([0-1]?[0-9]|2[0-4]):([0-5][0-9])(:[0-5][0-9])? ([pa]m|[PA]M)$");
                    return true;
                },
                msg: "Nhập"
            },
            ddlrequired: {
                check: function (value) {
                    if (value)
                        return true;
                    else
                        return false;
                },
                msg: " là bắt buộc."
            },
            rdrequired: {
                check: function (value) {
                    if (value)
                        return true;
                    else
                        return false;
                },
                msg: " là bắt buộc."
            },
            required: {
                check: function (value) {
                    if (value)
                        return true;
                    else
                        return false;
                },
                msg: " là bắt buộc."
            }
        }
        var testPattern = function (value, pattern) {

            var regExp = new RegExp(pattern, "");
            return regExp.test(value);
        }
        return {
            addRule: function (name, rule) {
                rules[name] = rule;
            },
            getRule: function (name) {
                return rules[name];
            }
        }
    }

    /* 
    Form factory 
    */
    var Form = function (form) {
        var fields = [];
        form.find("[validation]").each(function () {
            var field = $(this);
            if (field.attr('validation') !== undefined) {
                fields.push(new Field(field));
            }
        });
        this.fields = fields;
    }
    Form.prototype = {
        validate: function () {
            for (field in this.fields) {
                this.fields[field].validate();
            }
        },
        isValid: function () {
            for (field in this.fields) {
                if (!this.fields[field].valid) {
                    this.fields[field].field.focus();
                    return false;
                }
            }
            return true;
        }
    }

    /* 
    Field factory 
    */
    var Field = function (field) {
        this.field = field;
        this.valid = false;
        this.attach("change");
    }
    Field.prototype = {

        attach: function (event) {
            var obj = this;
            if (event == "change") {
                obj.field.bind("change", function () {
                    return obj.validate();
                });
            }
            if (event == "keyup") {
                obj.field.bind("keyup", function (e) {
                    return obj.validate();
                });
            }
        },
        validate: function () {

            var obj = this,
                groupErrorMessage = $('#errorMessages'),
                field = obj.field,
                errorClass = "error-desc",
                errorlist = $(document.createElement("label")).addClass(errorClass),
                types = field.attr("validation").split(" "),
                container = field.parent(),
                errors = [];

            container.find(".error-desc").remove();

            // Loop all error fields
            var message = "";

            for (var type in types) {
                var rule = $.Validation.getRule(types[type]);

                var radioListName = field.attr("name");
                var inputType = field.attr("type");
                var radioListValue = $("input[name=" + radioListName + "]:checked").val();

                if (rule != undefined && (!rule.check(field.val()) || (inputType == "radio" && !rule.check(radioListValue)))) {

                    if (types[type].toString() == "ddlrequired")
                        message = field.parents(".row").find("label").html() + " " + rule.msg;
                    else if (types[type].toString() == "rdrequired") {
                        message = field.parents(".row").find("label").html() + " " + rule.msg;
                    }
                    else if (types[type].toString() == "required")
                        message = field.parents(".row").find("label").html() + " " + rule.msg;
                    else if (types[type].toString() == "ssn") {
                        message = field.parents(".row").find("label").html() + " must be a social security number in the format xxx-xx-xxxx"
                    }
                    else
                        message = rule.msg + " " + field.parents(".row").find("label").html() + " hợp lệ.";
                    field.addClass("error");
                    errors.push(message);
                }
            }

            if (errors.length) {
                obj.field.unbind("keyup")
                obj.attach("keyup");
                field.after(errorlist.empty());

                // Show error on each field
                for (error in errors) {
                    var fieldType = field.attr("validation");

                    //alert(fieldType);

                    if (fieldType == "ddlrequired") {
                        var ddlfield = field.parents('.select-holder').find('.select-area');
                        ddlfield.addClass("error");
                        errorlist.html(errors[error]).insertBefore(ddlfield);
                    }
                    else if (fieldType == "rdrequired") {
                        var rdfield = field.parents('.groupinput');
                        rdfield.addClass("error");
                        rdfield.parents(".row").find(".error-desc").remove();

                        errorlist.html(errors[error]).insertBefore(rdfield);
                    }
                    else
                        errorlist.html(errors[error]).insertBefore(field);
                }
                obj.valid = false;
            }
            else {
                // Show/hide group message
                var messages = $('span.errorgrid').text().replace(/\s/g, '');
                if (messages.length > 0) {
                    groupErrorMessage.show();
                }
                else {
                    groupErrorMessage.hide();
                }

                errorlist.remove();
                field.removeClass("error");
                var fieldType = field.attr("validation");
                if (fieldType == "ddlrequired") {
                    var ddlfield = field.parents('.select-holder').find('.select-area');
                    ddlfield.removeClass("error");
                }
                else if (fieldType == "rdrequired") {
                    var rdfield = field.parents('.groupinput');
                    rdfield.removeClass("error");

                    // Remove error message
                    rdfield.parent(".row").find(".error-desc").remove();
                }
                obj.valid = true;
            }
        }
    }

    /*
    Validation extends jQuery prototype
    */
    $.extend($.fn, {
        validation: function () {
            var validator = new Form($(this));
            $.data($(this)[0], 'validator', validator);
            $(this).bind("submit", function (e) {
                validator.validate();
                if (!validator.isValid()) {
                    e.preventDefault();
                }
            });
        },
        validate: function () {
            var validator = $.data($(this)[0], 'validator');
            validator.validate();
            return validator.isValid();
        }
    });
    $.Validation = new Validation();
})(jQuery);